#include "hyper_lpr_sdk.h"
#include "opencv2/opencv.hpp"

#include <cstddef>
#include <vector>

static const std::vector<std::string> TYPES = {
    "蓝牌",     "黄牌单层", "白牌单层", "绿牌新能源", "黑牌港澳",
    "香港单层", "香港双层", "澳门单层", "澳门双层",   "黄牌双层"};

typedef struct {
  std::string file;
  std::string license;
  std::string color;

  int plate_left;
  int plate_top;
  int plate_right;
  int plate_bottom;

  int car_left;
  int car_top;
  int car_right;
  int car_bottom;
} Data;

int ReadDataSet(const std::string &label_file, std::vector<Data> &dataset) {
  std::ifstream is(label_file);

  if (!is.is_open()) {
    std::cerr << "open dataset label file error\n";
    return -1;
  }

  std::string line;
  while (std::getline(is, line)) {
    std::stringstream ss(line);
    std::vector<std::string> parts;
    std::string part;

    // 按照逗号分割当前行文本
    while (getline(ss, part, ',')) {
      parts.push_back(part);
    }

    if (parts.size() < 7) {
      std::cerr << "line error: " << line << std::endl;
      continue;
    }

    Data data{
        .file = parts[0],
        .license = parts[1],
        .color = parts[2],
        .plate_left = std::stoi(parts[3]),
        .plate_top = std::stoi(parts[4]),
        .plate_right = std::stoi(parts[5]),
        .plate_bottom = std::stoi(parts[6]),
        .car_left = std::stoi(parts[7]),
        .car_top = std::stoi(parts[8]),
        .car_right = std::stoi(parts[9]),
        .car_bottom = std::stoi(parts[10]),
    };

    dataset.push_back(data);
  }

  std::cout << "dataset count: " << dataset.size() << std::endl;
  return 0;
}

int main() {
  // hyperlpr
  const std::string model_path = "../hyperlpr3/resource/models/r2_mobile";
  // 配置车牌识别参数
  HLPR_ContextConfiguration configuration = {0};
  configuration.models_path = (char *)model_path.c_str(); // 模型文件夹路径
  configuration.max_num = 1;                  // 最大识别车牌数量
  configuration.det_level = DETECT_LEVEL_LOW; // 检测器等级
  configuration.use_half = false;
  configuration.nms_threshold = 0.5f; // 非极大值抑制置信度阈值
  configuration.rec_confidence_threshold = 0.5f; // 车牌号文本阈值
  configuration.box_conf_threshold = 0.30f;      // 检测器阈值
  configuration.threads = 1;
  // 实例化车牌识别算法Context
  P_HLPR_Context ctx = HLPR_CreateContext(&configuration);
  // 查询实例化状态
  HREESULT ret = HLPR_ContextQueryStatus(ctx);
  if (ret != HResultCode::Ok) {
    printf("create error.\n");
    return -1;
  }

  // dataset
  // const std::string dataset_path =
  // "/mnt/d/data/10.projects/camera-data-20241119/Python/python_sdk_demo/";
  const std::string dataset_path = "/home/teamhd/data/chuqq/lpr_dataset/";
  const std::string label_path = dataset_path + "labels_2_utf8.txt";

  std::vector<Data> dataset;
  ReadDataSet(label_path, dataset);

  std::string image_path;
  HLPR_ImageData data = {0};
  HLPR_PlateResultList results = {0};
  int total = 0;
  int correct = 0;
  for (const auto &item : dataset) {
    total += 1;
    // 读取jpeg
    image_path = dataset_path + item.file;
    cv::Mat im = cv::imread(image_path);

    // 抠出车图
    cv::Rect car_rect(item.car_left, item.car_top,
                      item.car_right - item.car_left,
                      item.car_bottom - item.car_top);
    cv::Mat car_image = im(car_rect);
    if (car_image.empty()) {
      std::cerr << "car image error: " << item.file << std::endl;
      continue;
    }
    cv::imwrite("car.jpg", car_image);
    cv::Mat image = cv::imread("car.jpg");

    // 车牌图
    // cv::Rect plate_rect(item.plate_left, item.plate_top,
    //                     item.plate_right - item.plate_left,
    //                     item.plate_bottom - item.plate_top);
    // cv::Mat plate_image = im(plate_rect);
    // if (plate_image.empty()) {
    //   std::cerr << "plate image error: " << item.file << std::endl;
    //   continue;
    // }
    // cv::imwrite("plate.jpg", plate_image);
    // cv::Mat image = cv::imread("plate.jpg");

    // 创建ImageData
    data = {0};
    data.data = image.ptr<uint8_t>(0); // 设置图像数据流
    data.width = image.cols;           // 设置图像宽
    data.height = image.rows;          // 设置图像高
    data.format = STREAM_BGR;          // 设置当前图像编码格式
    data.rotation = CAMERA_ROTATION_0; // 设置当前图像转角
    // 创建数据Buffer
    P_HLPR_DataBuffer buffer = HLPR_CreateDataBuffer(&data);

    // 执行车牌识别算法
    results = {0};
    HLPR_ContextUpdateStream(ctx, buffer, &results);

    // 销毁Buffer
    HLPR_ReleaseDataBuffer(buffer);

    if (results.plate_size > 0) {
      if (item.license == results.plates[0].code) {
        correct += 1;
      } else {
        std::cout << "error: " << item.file << " " << item.license << "->"
                  << results.plates[0].code << std::endl;
      }
    } else {
      std::cerr << "no plate: " << item.file << std::endl;
    }
  }

  // 销毁Context
  HLPR_ReleaseContext(ctx);

  // 统计
  std::cout << "correct: " << correct << "/ total: " << total
            << ". acc: " << float(correct) / total << std::endl;

  return 0;
}
